#include "EarthWidget.h"
#include <QOpenGLShader>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QDebug>
#include <QFile>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QEventLoop>
#include <QTime>
#include <QTimer>
#include <QApplication>
#include <QDir>
#include <QStandardPaths>
#include <random>
#include <cmath>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

EarthWidget::EarthWidget(QWidget *parent)
    : QOpenGLWidget(parent),
    m_distance(5.0f),
    m_rotationX(0.0f),
    m_rotationY(0.0f),
    m_stacks(50),
    m_slices(50),
    m_radius(1.0f),
    m_textureLoaded(false),
    m_earthProgram(nullptr),
    m_markerProgram(nullptr),
    m_starProgram(nullptr),
    m_modelProgram(nullptr),
    m_earthTexture(0),
    m_ambientStrength(0.3f),
    m_isRotating(false),
    m_starCount(1000)
{
    setFocusPolicy(Qt::StrongFocus);
    m_networkManager = new QNetworkAccessManager(this);
    connect(m_networkManager, &QNetworkAccessManager::finished,
            this, &EarthWidget::onTextureDownloaded);

    // 创建动画计时器
    m_animationTimer = new QTimer(this);
    connect(m_animationTimer, &QTimer::timeout, this, &EarthWidget::updateAnimation);
    m_animationTimer->start(50); // 20 FPS

    m_time.start();

    // 初始化路径
    initializePaths();

    // 设置多个光源
    setupMultipleLights();
}

EarthWidget::~EarthWidget()
{
    makeCurrent();

    m_earthVao.destroy();
    m_earthVbo.destroy();
    m_earthIbo.destroy();
    m_markerVao.destroy();
    m_markerVbo.destroy();
    m_markerIbo.destroy();
    m_starVao.destroy();
    m_starVbo.destroy();

    if (m_textureLoaded && m_earthTexture != 0) {
        glDeleteTextures(1, &m_earthTexture);
    }

    delete m_earthProgram;
    delete m_markerProgram;
    delete m_starProgram;

    doneCurrent();
}

void EarthWidget::setupMultipleLights()
{
    m_lights.clear();

    // 主光源 - 太阳（强光）
    Light mainLight;
    mainLight.position = QVector3D(10.0f, 5.0f, 10.0f);
    mainLight.color = QVector3D(1.0f, 0.95f, 0.8f); // 温暖的阳光色
    mainLight.intensity = 1.0f;
    m_lights.append(mainLight);

    // 辅助光源1 - 补光（从另一侧）
    Light fillLight;
    fillLight.position = QVector3D(-8.0f, 3.0f, -8.0f);
    fillLight.color = QVector3D(0.7f, 0.8f, 1.0f); // 冷色调补光
    fillLight.intensity = 0.4f;
    m_lights.append(fillLight);

    // 辅助光源2 - 环境光（从上方）
    Light ambientLight;
    ambientLight.position = QVector3D(0.0f, 10.0f, 0.0f);
    ambientLight.color = QVector3D(1.0f, 1.0f, 1.0f);
    ambientLight.intensity = 0.3f;
    m_lights.append(ambientLight);

    // 辅助光源3 - 背光（从后方）
    Light backLight;
    backLight.position = QVector3D(0.0f, 0.0f, -12.0f);
    backLight.color = QVector3D(0.9f, 0.9f, 1.0f);
    backLight.intensity = 0.2f;
    m_lights.append(backLight);
}

// 路径管理函数
QString EarthWidget::getApplicationPath() {
    return QApplication::applicationDirPath();
}

QString EarthWidget::getTexturesPath() {
    QString texturesPath = getApplicationPath() + "/textures";
    QDir dir(texturesPath);
    if (!dir.exists()) {
        dir.mkpath(".");
    }
    return texturesPath;
}

QString EarthWidget::getCachePath() {
    QString cachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
    QDir dir(cachePath);
    if (!dir.exists()) {
        dir.mkpath(".");
    }
    return cachePath;
}

bool EarthWidget::loadLocalTexture(const QString& relativePath) {
    QString fullPath = getApplicationPath() + "/" + relativePath;
    return loadEarthTexture(fullPath);
}

bool EarthWidget::saveDownloadedTexture(const QImage& image, const QString& filename) {
    QString cachePath = getCachePath();
    QString filePath = cachePath + "/" + filename;

    if (image.save(filePath)) {
        qDebug() << "纹理已保存到:" << filePath;
        return true;
    }
    return false;
}

QString EarthWidget::getCachedTexturePath(const QString& filename) {
    return getCachePath() + "/" + filename;
}

bool EarthWidget::loadCachedTexture(const QString& filename) {
    QString cachedPath = getCachedTexturePath(filename);
    if (QFile::exists(cachedPath)) {
        return loadEarthTexture(cachedPath);
    }
    return false;
}

void EarthWidget::initializePaths() {
    // 创建必要的目录
    getTexturesPath();
    getCachePath();

    qDebug() << "应用程序路径:" << getApplicationPath();
    qDebug() << "纹理路径:" << getTexturesPath();
    qDebug() << "缓存路径:" << getCachePath();
}

void EarthWidget::initializeGL()
{
    initializeOpenGLFunctions();

    qDebug() << "OpenGL initialized, version:" << QString((const char*)glGetString(GL_VERSION));

    // 设置黑色背景
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);

    // 创建地球着色器程序（多光源支持）
    m_earthProgram = new QOpenGLShaderProgram;
    m_earthProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
                                            "#version 330 core\n"
                                            "layout(location = 0) in vec3 position;\n"
                                            "layout(location = 1) in vec3 normal;\n"
                                            "layout(location = 2) in vec2 texCoord;\n"
                                            "out vec3 FragPos;\n"
                                            "out vec3 Normal;\n"
                                            "out vec2 TexCoord;\n"
                                            "uniform mat4 mvp_matrix;\n"
                                            "uniform mat4 model_matrix;\n"
                                            "void main()\n"
                                            "{\n"
                                            "    FragPos = vec3(model_matrix * vec4(position, 1.0));\n"
                                            "    Normal = mat3(transpose(inverse(model_matrix))) * normal;\n"
                                            "    TexCoord = texCoord;\n"
                                            "    gl_Position = mvp_matrix * vec4(position, 1.0);\n"
                                            "}");

    m_earthProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
                                            "#version 330 core\n"
                                            "in vec3 FragPos;\n"
                                            "in vec3 Normal;\n"
                                            "in vec2 TexCoord;\n"
                                            "out vec4 FragColor;\n"
                                            "uniform sampler2D texture_sampler;\n"
                                            "uniform bool hasTexture;\n"
                                            "uniform vec3 viewPos;\n"
                                            "uniform float ambientStrength;\n"
                                            "\n"
                                            "struct Light {\n"
                                            "    vec3 position;\n"
                                            "    vec3 color;\n"
                                            "    float intensity;\n"
                                            "};\n"
                                            "\n"
                                            "const int MAX_LIGHTS = 4;\n"
                                            "uniform Light lights[MAX_LIGHTS];\n"
                                            "\n"
                                            "void main()\n"
                                            "{\n"
                                            "    vec3 ambient = ambientStrength * vec3(1.0);\n"
                                            "    \n"
                                            "    vec3 totalLight = vec3(0.0);\n"
                                            "    \n"
                                            "    for(int i = 0; i < MAX_LIGHTS; i++) {\n"
                                            "        vec3 norm = normalize(Normal);\n"
                                            "        vec3 lightDir = normalize(lights[i].position - FragPos);\n"
                                            "        float diff = max(dot(norm, lightDir), 0.0);\n"
                                            "        \n"
                                            "        vec3 viewDir = normalize(viewPos - FragPos);\n"
                                            "        vec3 reflectDir = reflect(-lightDir, norm);\n"
                                            "        float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);\n"
                                            "        \n"
                                            "        vec3 diffuse = diff * lights[i].color * lights[i].intensity;\n"
                                            "        vec3 specular = spec * lights[i].color * lights[i].intensity * 0.5;\n"
                                            "        \n"
                                            "        totalLight += diffuse + specular;\n"
                                            "    }\n"
                                            "    \n"
                                            "    vec4 texColor;\n"
                                            "    if (hasTexture) {\n"
                                            "        texColor = texture(texture_sampler, TexCoord);\n"
                                            "        texColor.rgb = texColor.rgb * 1.1;\n"
                                            "    } else {\n"
                                            "        texColor = vec4(0.0, 0.4, 0.8, 1.0);\n"
                                            "    }\n"
                                            "    \n"
                                            "    vec3 result = (ambient + totalLight) * texColor.rgb;\n"
                                            "    \n"
                                            "    result = max(result, vec3(0.15));\n"
                                            "    \n"
                                            "    result = pow(result, vec3(0.9));\n"
                                            "    \n"
                                            "    FragColor = vec4(result, 1.0);\n"
                                            "}");

    if (!m_earthProgram->link()) {
        qWarning() << "Earth shader program link failed:" << m_earthProgram->log();
    }

    // 创建标记着色器程序
    m_markerProgram = new QOpenGLShaderProgram;
    m_markerProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
                                             "#version 330 core\n"
                                             "layout(location = 0) in vec3 position;\n"
                                             "layout(location = 1) in vec3 normal;\n"
                                             "layout(location = 2) in vec2 texCoord;\n"
                                             "uniform mat4 mvp_matrix;\n"
                                             "void main()\n"
                                             "{\n"
                                             "    gl_Position = mvp_matrix * vec4(position, 1.0);\n"
                                             "}");

    m_markerProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
                                             "#version 330 core\n"
                                             "out vec4 FragColor;\n"
                                             "uniform vec3 color;\n"
                                             "void main()\n"
                                             "{\n"
                                             "    FragColor = vec4(color, 1.0);\n"
                                             "}");

    if (!m_markerProgram->link()) {
        qWarning() << "Marker shader program link failed:" << m_markerProgram->log();
    }

    // 创建星星着色器程序
    m_starProgram = new QOpenGLShaderProgram;
    m_starProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
                                           "#version 330 core\n"
                                           "layout(location = 0) in vec3 position;\n"
                                           "layout(location = 1) in float brightness;\n"
                                           "out float vBrightness;\n"
                                           "uniform mat4 mvp_matrix;\n"
                                           "uniform float time;\n"
                                           "void main()\n"
                                           "{\n"
                                           "    vBrightness = brightness * (0.8 + 0.4 * sin(time * 3.0 + position.x * 10.0));\n"
                                           "    gl_Position = mvp_matrix * vec4(position, 1.0);\n"
                                           "    gl_PointSize = 2.0 * vBrightness;\n"
                                           "}");

    m_starProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
                                           "#version 330 core\n"
                                           "in float vBrightness;\n"
                                           "out vec4 FragColor;\n"
                                           "void main()\n"
                                           "{\n"
                                           "    float dist = length(gl_PointCoord - vec2(0.5));\n"
                                           "    if (dist > 0.5) discard;\n"
                                           "    float alpha = vBrightness * (1.0 - dist * 2.0);\n"
                                           "    FragColor = vec4(1.0, 1.0, 1.0, alpha);\n"
                                           "}");

    if (!m_starProgram->link()) {
        qWarning() << "Star shader program link failed:" << m_starProgram->log();
    }

    // 创建模型着色器程序
    m_modelProgram = new QOpenGLShaderProgram;
    m_modelProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
                                            "#version 330 core\n"
                                            "layout(location = 0) in vec3 position;\n"
                                            "layout(location = 1) in vec3 normal;\n"
                                            "layout(location = 2) in vec2 texCoord;\n"
                                            "out vec3 FragPos;\n"
                                            "out vec3 Normal;\n"
                                            "out vec2 TexCoord;\n"
                                            "uniform mat4 mvp_matrix;\n"
                                            "uniform mat4 model_matrix;\n"
                                            "void main()\n"
                                            "{\n"
                                            "    FragPos = vec3(model_matrix * vec4(position, 1.0));\n"
                                            "    Normal = mat3(transpose(inverse(model_matrix))) * normal;\n"
                                            "    TexCoord = texCoord;\n"
                                            "    gl_Position = mvp_matrix * vec4(position, 1.0);\n"
                                            "}");

    m_modelProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
                                            "#version 330 core\n"
                                            "in vec3 FragPos;\n"
                                            "in vec3 Normal;\n"
                                            "in vec2 TexCoord;\n"
                                            "out vec4 FragColor;\n"
                                            "uniform sampler2D texture_sampler;\n"
                                            "uniform bool hasTexture;\n"
                                            "uniform vec3 viewPos;\n"
                                            "uniform float ambientStrength;\n"
                                            "\n"
                                            "struct Light {\n"
                                            "    vec3 position;\n"
                                            "    vec3 color;\n"
                                            "    float intensity;\n"
                                            "};\n"
                                            "\n"
                                            "const int MAX_LIGHTS = 4;\n"
                                            "uniform Light lights[MAX_LIGHTS];\n"
                                            "\n"
                                            "void main()\n"
                                            "{\n"
                                            "    vec3 ambient = ambientStrength * vec3(1.0);\n"
                                            "    \n"
                                            "    vec3 totalLight = vec3(0.0);\n"
                                            "    \n"
                                            "    for(int i = 0; i < MAX_LIGHTS; i++) {\n"
                                            "        vec3 norm = normalize(Normal);\n"
                                            "        vec3 lightDir = normalize(lights[i].position - FragPos);\n"
                                            "        float diff = max(dot(norm, lightDir), 0.0);\n"
                                            "        \n"
                                            "        vec3 viewDir = normalize(viewPos - FragPos);\n"
                                            "        vec3 reflectDir = reflect(-lightDir, norm);\n"
                                            "        float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);\n"
                                            "        \n"
                                            "        vec3 diffuse = diff * lights[i].color * lights[i].intensity;\n"
                                            "        vec3 specular = spec * lights[i].color * lights[i].intensity * 0.3;\n"
                                            "        \n"
                                            "        totalLight += diffuse + specular;\n"
                                            "    }\n"
                                            "    \n"
                                            "    vec4 texColor;\n"
                                            "    if (hasTexture) {\n"
                                            "        texColor = texture(texture_sampler, TexCoord);\n"
                                            "    } else {\n"
                                            "        texColor = vec4(0.8, 0.8, 0.8, 1.0); \n"
                                            "    }\n"
                                            "    \n"
                                            "    vec3 result = (ambient + totalLight) * texColor.rgb;\n"
                                            "    FragColor = vec4(result, 1.0);\n"
                                            "}");

    if (!m_modelProgram->link()) {
        qWarning() << "Model shader program link failed:" << m_modelProgram->log();
    }

    // 创建几何体
    createSphereGeometry();
    createMarkerGeometry();
    createStarsGeometry();

    // 创建默认纹理
    createDefaultTexture();

    this->loadEarthTexture(QApplication::applicationDirPath()+"/2k_earth_daymap.jpg");
    this->loadModel(QApplication::applicationDirPath()+"/cottage_obj.obj",
                    QApplication::applicationDirPath()+"/cottage_obj.png");
}

void EarthWidget::createStarsGeometry()
{
    m_stars.clear();

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(-15.0, 15.0);
    std::uniform_real_distribution<> brightDis(0.3, 1.0);
    std::uniform_real_distribution<> speedDis(1.0, 5.0);

    // 生成随机星星
    for (int i = 0; i < m_starCount; ++i) {
        Star star;
        star.position = QVector3D(
            dis(gen),
            dis(gen),
            dis(gen)
            );
        // 确保星星在视野范围内
        if (star.position.length() < 2.0f) {
            star.position = star.position.normalized() * 2.0f;
        }
        star.brightness = brightDis(gen);
        star.flickerSpeed = speedDis(gen);
        m_stars.append(star);
    }

    // 创建星星VBO
    m_starVao.create();
    m_starVao.bind();

    m_starVbo = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    m_starVbo.create();
    m_starVbo.bind();
    m_starVbo.allocate(m_stars.constData(), m_stars.size() * sizeof(Star));

    m_starProgram->bind();

    // 设置属性指针
    m_starProgram->enableAttributeArray(0);
    m_starProgram->setAttributeBuffer(0, GL_FLOAT, offsetof(Star, position), 3, sizeof(Star));

    m_starProgram->enableAttributeArray(1);
    m_starProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(Star, brightness), 1, sizeof(Star));

    m_starVao.release();
}

void EarthWidget::updateAnimation()
{
    update(); // 触发重绘
}

void EarthWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    m_projection.setToIdentity();
    m_projection.perspective(45.0f, GLfloat(w) / h, 0.01f, 100.0f);
}

void EarthWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    updateCamera();

    // 绘制星星（首先绘制，作为背景）
    glEnable(GL_PROGRAM_POINT_SIZE);
    glEnable(GL_BLEND);
    glDepthMask(GL_FALSE);

    m_starProgram->bind();
    m_starProgram->setUniformValue("mvp_matrix", m_projection * m_view);
    m_starProgram->setUniformValue("time", m_time.elapsed() / 1000.0f);

    m_starVao.bind();
    glDrawArrays(GL_POINTS, 0, m_stars.size());
    m_starVao.release();

    glDepthMask(GL_TRUE);
    glDisable(GL_BLEND);

    // 绘制地球 - 使用多光源系统
    m_earthProgram->bind();
    m_earthProgram->setUniformValue("mvp_matrix", m_projection * m_view * m_model);
    m_earthProgram->setUniformValue("model_matrix", m_model);
    m_earthProgram->setUniformValue("hasTexture", m_textureLoaded);
    m_earthProgram->setUniformValue("viewPos", QVector3D(0.0f, 0.0f, m_distance));
    m_earthProgram->setUniformValue("ambientStrength", m_ambientStrength);

    // 设置多个光源
    for (int i = 0; i < m_lights.size(); ++i) {
        QString lightPos = QString("lights[%1].position").arg(i);
        QString lightColor = QString("lights[%1].color").arg(i);
        QString lightIntensity = QString("lights[%1].intensity").arg(i);

        m_earthProgram->setUniformValue(lightPos.toUtf8().constData(), m_lights[i].position);
        m_earthProgram->setUniformValue(lightColor.toUtf8().constData(), m_lights[i].color);
        m_earthProgram->setUniformValue(lightIntensity.toUtf8().constData(), m_lights[i].intensity);
    }

    if (m_textureLoaded) {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, m_earthTexture);
        m_earthProgram->setUniformValue("texture_sampler", 0);
    }

    m_earthVao.bind();
    glDrawElements(GL_TRIANGLES, m_earthIndices.size(), GL_UNSIGNED_INT, nullptr);
    m_earthVao.release();

    m_markerProgram->bind();
    for (const Marker& marker : m_markers) {
        m_markerProgram->setUniformValue("mvp_matrix", m_projection * m_view * marker.modelMatrix);
        m_markerProgram->setUniformValue("color", marker.color);

        m_markerVao.bind();
        glDrawElements(GL_TRIANGLES, m_markerIndices.size(), GL_UNSIGNED_INT, nullptr);
        m_markerVao.release();
    }

    // 绘制3D模型（在地球之后绘制）
    if (!m_placedModels.isEmpty()) {
        drawModels();
    }

    m_earthProgram->release();
    m_markerProgram->release();
    m_starProgram->release();
    m_modelProgram->release();
}

void EarthWidget::drawModels()
{
    m_modelProgram->bind();
    m_modelProgram->setUniformValue("viewPos", QVector3D(0.0f, 0.0f, m_distance));
    m_modelProgram->setUniformValue("ambientStrength", 0.8f); // 增强环境光

    // 设置光源
    for (int i = 0; i < m_lights.size(); ++i) {
        QString lightPos = QString("lights[%1].position").arg(i);
        QString lightColor = QString("lights[%1].color").arg(i);
        QString lightIntensity = QString("lights[%1].intensity").arg(i);

        m_modelProgram->setUniformValue(lightPos.toUtf8().constData(), m_lights[i].position);
        m_modelProgram->setUniformValue(lightColor.toUtf8().constData(), m_lights[i].color);
        m_modelProgram->setUniformValue(lightIntensity.toUtf8().constData(), m_lights[i].intensity);
    }

    for (int i = 0; i < m_placedModels.size(); ++i) {
        const PlacedModel& placedModel = m_placedModels[i];

        if (m_loadedModels.contains(placedModel.modelName)) {
            const ModelData& modelData = m_loadedModels[placedModel.modelName];

            m_modelProgram->setUniformValue("mvp_matrix", m_projection * m_view * placedModel.modelMatrix);
            m_modelProgram->setUniformValue("model_matrix", placedModel.modelMatrix);
            m_modelProgram->setUniformValue("hasTexture", modelData.textureLoaded);

            if (modelData.textureLoaded) {
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, modelData.texture);
                m_modelProgram->setUniformValue("texture_sampler", 0);
            }

            // 绘制模型几何体
            drawModelGeometry(modelData);
        }
    }

    m_modelProgram->release();
}

void EarthWidget::updateCamera()
{
    m_view.setToIdentity();
    m_view.translate(0.0f, 0.0f, -m_distance);
    m_view.rotate(m_rotationX, 1.0f, 0.0f, 0.0f);
    m_view.rotate(m_rotationY, 0.0f, 1.0f, 0.0f);

    m_model.setToIdentity();
}

bool EarthWidget::loadOBJModel(const QString& path, ModelData& model)
{
    QFile file(path);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "无法打开OBJ文件:" << path;
        return false;
    }

    QVector<QVector3D> vertices;
    QVector<QVector3D> normals;
    QVector<QVector2D> texCoords;
    QVector<VertexData> tempVertices;

    QTextStream in(&file);
    while (!in.atEnd()) {
        QString line = in.readLine().trimmed();
        if (line.isEmpty() || line.startsWith("#")) continue;

        QStringList parts = line.split(" ", Qt::SkipEmptyParts);
        if (parts.isEmpty()) continue;

        if (parts[0] == "v") { // 顶点
            if (parts.size() >= 4) {
                float x = parts[1].toFloat();
                float y = parts[2].toFloat();
                float z = parts[3].toFloat();
                vertices.append(QVector3D(x, y, z));
            }
        } else if (parts[0] == "vn") { // 法线
            if (parts.size() >= 4) {
                float x = parts[1].toFloat();
                float y = parts[2].toFloat();
                float z = parts[3].toFloat();
                normals.append(QVector3D(x, y, z));
            }
        } else if (parts[0] == "vt") { // 纹理坐标
            if (parts.size() >= 3) {
                float u = parts[1].toFloat();
                float v = 1.0f - parts[2].toFloat(); // OBJ纹理坐标需要翻转Y轴
                texCoords.append(QVector2D(u, v));
            }
        } else if (parts[0] == "f") { // 面 - 需要正确处理三角面和四边形面
            if (parts.size() < 4) continue;

            QVector<QStringList> faceVertices;
            for (int i = 1; i < parts.size(); i++) {
                faceVertices.append(parts[i].split("/"));
            }

            // 三角化 (扇形三角化)
            for (int i = 1; i < faceVertices.size() - 1; i++) {
                // 三个顶点构成一个三角形
                for (int j = 0; j < 3; j++) {
                    int vertexIndex = 0;
                    if (j == 0) vertexIndex = 0;
                    else if (j == 1) vertexIndex = i;
                    else vertexIndex = i + 1;

                    VertexData vertex;

                    // 顶点位置
                    if (faceVertices[vertexIndex].size() > 0 && !faceVertices[vertexIndex][0].isEmpty()) {
                        int idx = faceVertices[vertexIndex][0].toInt() - 1;
                        if (idx >= 0 && idx < vertices.size()) {
                            vertex.position = vertices[idx];
                        }
                    }

                    // 纹理坐标
                    if (faceVertices[vertexIndex].size() > 1 && !faceVertices[vertexIndex][1].isEmpty()) {
                        int idx = faceVertices[vertexIndex][1].toInt() - 1;
                        if (idx >= 0 && idx < texCoords.size()) {
                            vertex.texCoord = texCoords[idx];
                        } else {
                            vertex.texCoord = QVector2D(0.0f, 0.0f);
                        }
                    } else {
                        vertex.texCoord = QVector2D(0.0f, 0.0f);
                    }

                    // 法线
                    if (faceVertices[vertexIndex].size() > 2 && !faceVertices[vertexIndex][2].isEmpty()) {
                        int idx = faceVertices[vertexIndex][2].toInt() - 1;
                        if (idx >= 0 && idx < normals.size()) {
                            vertex.normal = normals[idx];
                        } else {
                            vertex.normal = QVector3D(0.0f, 1.0f, 0.0f);
                        }
                    } else {
                        vertex.normal = QVector3D(0.0f, 1.0f, 0.0f);
                    }

                    tempVertices.append(vertex);
                }
            }
        }
    }

    file.close();

    if (tempVertices.isEmpty()) {
        qWarning() << "No vertices loaded from OBJ file:" << path;
        return false;
    }

    // 如果模型没有法线，计算面法线
    if (normals.isEmpty()) {
        calculateModelNormals(tempVertices);
    }

    model.vertices = tempVertices;

    // 生成索引
    model.indices.clear();
    for (GLuint i = 0; i < model.vertices.size(); i++) {
        model.indices.append(i);
    }

    qDebug() << "加载OBJ模型成功:" << path << "顶点数:" << model.vertices.size();
    return true;
}

void EarthWidget::calculateModelNormals(QVector<VertexData>& vertices)
{
    // 为每个顶点初始化法线
    for (int i = 0; i < vertices.size(); i++) {
        vertices[i].normal = QVector3D(0.0f, 0.0f, 0.0f);
    }

    // 计算每个面的法线并累加到顶点
    for (int i = 0; i < vertices.size(); i += 3) {
        if (i + 2 < vertices.size()) {
            QVector3D v1 = vertices[i].position;
            QVector3D v2 = vertices[i+1].position;
            QVector3D v3 = vertices[i+2].position;

            QVector3D edge1 = v2 - v1;
            QVector3D edge2 = v3 - v1;
            QVector3D faceNormal = QVector3D::crossProduct(edge1, edge2).normalized();

            vertices[i].normal += faceNormal;
            vertices[i+1].normal += faceNormal;
            vertices[i+2].normal += faceNormal;
        }
    }

    // 标准化所有法线
    for (int i = 0; i < vertices.size(); i++) {
        vertices[i].normal.normalize();
    }
}

void EarthWidget::drawModelGeometry(const ModelData& model)
{
    // 为每个模型创建临时的VAO/VBO
    static QMap<QString, QOpenGLVertexArrayObject*> modelVaos;
    static QMap<QString, QOpenGLBuffer*> modelVbos;
    static QMap<QString, QOpenGLBuffer*> modelIbos;

    // 修复：直接使用模型指针地址作为键，不依赖QMap的key方法
    QString modelKey = QString("model_%1").arg(reinterpret_cast<quintptr>(&model));

    if (!modelVaos.contains(modelKey)) {
        // 创建模型的VAO/VBO
        QOpenGLVertexArrayObject* vao = new QOpenGLVertexArrayObject;
        QOpenGLBuffer* vbo = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
        QOpenGLBuffer* ibo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);

        if (!vao->create() || !vbo->create() || !ibo->create()) {
            qWarning() << "Failed to create OpenGL buffers for model";
            delete vao;
            delete vbo;
            delete ibo;
            return;
        }

        vao->bind();

        vbo->bind();
        vbo->allocate(model.vertices.constData(), model.vertices.size() * sizeof(VertexData));

        ibo->bind();
        ibo->allocate(model.indices.constData(), model.indices.size() * sizeof(GLuint));

        m_modelProgram->bind();

        // 设置属性指针
        m_modelProgram->enableAttributeArray(0);
        m_modelProgram->setAttributeBuffer(0, GL_FLOAT, offsetof(VertexData, position), 3, sizeof(VertexData));

        m_modelProgram->enableAttributeArray(1);
        m_modelProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(VertexData, normal), 3, sizeof(VertexData));

        m_modelProgram->enableAttributeArray(2);
        m_modelProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(VertexData, texCoord), 2, sizeof(VertexData));

        vao->release();
        vbo->release();
        ibo->release();

        modelVaos[modelKey] = vao;
        modelVbos[modelKey] = vbo;
        modelIbos[modelKey] = ibo;

        qDebug() << "Created OpenGL buffers for model:" << modelKey;
    }

    // 绘制模型
    if (modelVaos.contains(modelKey)) {
        modelVaos[modelKey]->bind();
        glDrawElements(GL_TRIANGLES, model.indices.size(), GL_UNSIGNED_INT, nullptr);
        modelVaos[modelKey]->release();
    }
}

bool EarthWidget::loadModelTexture(const QString& path, ModelData& model)
{
    makeCurrent();

    QImage textureImage(path);
    if (textureImage.isNull()) {
        qWarning() << "无法加载纹理图片:" << path;
        doneCurrent();
        return false;
    }

    textureImage = textureImage.convertToFormat(QImage::Format_RGBA8888).mirrored();

    GLuint textureId = 0;
    glGenTextures(1, &textureId);

    if (textureId == 0) {
        qWarning() << "无法生成纹理ID:" << path;
        doneCurrent();
        return false;
    }

    glBindTexture(GL_TEXTURE_2D, textureId);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                 textureImage.width(), textureImage.height(), 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, textureImage.bits());

    glGenerateMipmap(GL_TEXTURE_2D);

    GLenum error = glGetError();
    if (error != GL_NO_ERROR) {
        qWarning() << "OpenGL纹理加载错误:" << error;
        glDeleteTextures(1, &textureId);
        doneCurrent();
        return false;
    }

    model.texture = textureId;
    model.textureLoaded = true;

    doneCurrent();

    qDebug() << "模型纹理加载成功:" << path << "纹理ID:" << textureId;
    return true;
}

bool EarthWidget::loadModel(const QString& objPath, const QString& texturePath)
{
    ModelData model;
    model.textureLoaded = false;
    model.scale = QVector3D(1.0f, 1.0f, 1.0f);
    model.rotation = 0.0f;

    // 加载OBJ模型
    if (!loadOBJModel(objPath, model)) {
        return false;
    }

    // 加载纹理（如果提供）
    if (!texturePath.isEmpty()) {
        if (!loadModelTexture(texturePath, model)) {
        }
    }

    // 保存模型
    QString modelName = QFileInfo(objPath).baseName();
    m_loadedModels[modelName] = model;

    qDebug() << "模型加载完成:" << modelName
             << "顶点数:" << model.vertices.size()
             << "索引数:" << model.indices.size()
             << "texture:" << (model.textureLoaded ? "yes" : "no");

    // 自动在测试位置放置一个模型用于调试
    //addModelAtLocation(0.0f, 0.0f, modelName, QVector3D(0.1f, 0.1f, 0.1f));

    return true;
}

QVector3D EarthWidget::geographicToCartesian(float latitude, float longitude)
{
    float latRad = latitude * M_PI / 180.0f;
    float lonRad = longitude * M_PI / 180.0f;

    float x = m_radius * std::cos(latRad) * std::cos(lonRad);
    float y = m_radius * std::sin(latRad);
    float z = m_radius * std::cos(latRad) * std::sin(lonRad);

    return QVector3D(x, y, z);
}

void EarthWidget::addModelAtLocation(float latitude, float longitude, const QString& modelName, const QVector3D& scale)
{
    if (!m_loadedModels.contains(modelName)) {
        qWarning() << "模型未加载:" << modelName;
        return;
    }

    // 将地理坐标转换为球面坐标
    QVector3D position = geographicToCartesian(latitude, longitude);

    // 将模型放置在地球表面上方，避免嵌入地球
    float offset = 0.15f; // 增加偏移量
    QVector3D modelPosition = position * (1.0f + offset);

    PlacedModel placedModel;
    placedModel.modelName = modelName;
    placedModel.position = modelPosition;
    placedModel.scale = scale;
    placedModel.rotation = 0.0f;

    // 创建变换矩阵 - 使模型朝向正确方向
    placedModel.modelMatrix.setToIdentity();
    placedModel.modelMatrix.translate(modelPosition);

    // 计算旋转使模型垂直于球面
    QVector3D normal = position.normalized();
    QVector3D up(0.0f, 1.0f, 0.0f);
    QVector3D right = QVector3D::crossProduct(up, normal).normalized();
    QVector3D localUp = QVector3D::crossProduct(normal, right).normalized();

    QMatrix4x4 rotation;
    rotation.setColumn(0, QVector4D(right, 0.0f));
    rotation.setColumn(1, QVector4D(localUp, 0.0f));
    rotation.setColumn(2, QVector4D(normal, 0.0f));

    placedModel.modelMatrix = placedModel.modelMatrix * rotation;
    placedModel.modelMatrix.scale(scale);

    m_placedModels.append(placedModel);

    qDebug() << "在地球位置添加模型:" << modelName
             << "纬度:" << latitude << "经度:" << longitude
             << "位置:" << modelPosition
             << "缩放:" << scale;

    emit modelAdded(latitude, longitude, modelName);
    update();
}

void EarthWidget::clearModels()
{
    m_placedModels.clear();
    update();
}

GLuint EarthWidget::loadTexture(const QImage& image)
{
    if (!isValid()) {
        qWarning() << "OpenGL context is not valid!";
        return 0;
    }

    GLuint textureId = 0;
    glGenTextures(1, &textureId);

    if (textureId == 0) {
        qWarning() << "Failed to generate texture ID";
        return 0;
    }

    glBindTexture(GL_TEXTURE_2D, textureId);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                 image.width(), image.height(), 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, image.bits());

    glGenerateMipmap(GL_TEXTURE_2D);

    GLenum error = glGetError();
    if (error != GL_NO_ERROR) {
        qWarning() << "OpenGL error:" << error;
    }

    qDebug() << "Texture loaded successfully, ID:" << textureId
             << "Size:" << image.width() << "x" << image.height();

    return textureId;
}

void EarthWidget::createDefaultTexture()
{
    const int texSize = 256;
    QImage defaultTexture(texSize, texSize, QImage::Format_RGBA8888);

    for (int y = 0; y < texSize; ++y) {
        for (int x = 0; x < texSize; ++x) {
            QColor color;
            float fx = static_cast<float>(x) / texSize;
            float fy = static_cast<float>(y) / texSize;

            float noise = std::sin(fx * 10) * std::cos(fy * 10);

            if (noise > 0.3f) {
                color = QColor(50, 160, 50); // 更亮的陆地颜色
            } else if (noise > 0.1f) {
                color = QColor(230, 200, 160); // 更亮的沙滩颜色
            } else {
                color = QColor(30, 130, 200); // 更亮的海洋颜色
            }

            defaultTexture.setPixelColor(x, y, color);
        }
    }

    makeCurrent();

    if (m_earthTexture != 0) {
        glDeleteTextures(1, &m_earthTexture);
    }

    m_earthTexture = loadTexture(defaultTexture);
    m_textureLoaded = (m_earthTexture != 0);

    doneCurrent();

    if (m_textureLoaded) {
        qDebug() << "Default texture created successfully";
    } else {
        qWarning() << "Failed to create default texture";
    }
}

void EarthWidget::createSphereGeometry()
{
    m_earthVertices.clear();
    m_earthIndices.clear();

    // 生成球体顶点
    for (int stack = 0; stack <= m_stacks; ++stack) {
        float phi = M_PI * stack / m_stacks;
        for (int slice = 0; slice <= m_slices; ++slice) {
            float theta = 2 * M_PI * slice / m_slices;

            float x = std::sin(phi) * std::cos(theta);
            float y = std::cos(phi);
            float z = std::sin(phi) * std::sin(theta);

            VertexData vertex;
            vertex.position = QVector3D(x * m_radius, y * m_radius, z * m_radius);
            vertex.normal = QVector3D(x, y, z);

            float u = 1.0f - static_cast<float>(slice) / m_slices;
            float v = static_cast<float>(stack) / m_stacks;

            vertex.texCoord = QVector2D(u, v);

            m_earthVertices.append(vertex);
        }
    }

    // 生成球体索引
    for (int stack = 0; stack < m_stacks; ++stack) {
        for (int slice = 0; slice < m_slices; ++slice) {
            int first = stack * (m_slices + 1) + slice;
            int second = first + m_slices + 1;

            m_earthIndices.append(first);
            m_earthIndices.append(second);
            m_earthIndices.append(first + 1);

            m_earthIndices.append(second);
            m_earthIndices.append(second + 1);
            m_earthIndices.append(first + 1);
        }
    }

    // 设置地球VAO和VBO
    m_earthVao.create();
    m_earthVao.bind();

    m_earthVbo = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    m_earthVbo.create();
    m_earthVbo.bind();
    m_earthVbo.allocate(m_earthVertices.constData(), m_earthVertices.size() * sizeof(VertexData));

    m_earthIbo = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
    m_earthIbo.create();
    m_earthIbo.bind();
    m_earthIbo.allocate(m_earthIndices.constData(), m_earthIndices.size() * sizeof(GLuint));

    // 设置属性指针
    m_earthProgram->bind();

    m_earthProgram->enableAttributeArray(0);
    m_earthProgram->setAttributeBuffer(0, GL_FLOAT, offsetof(VertexData, position), 3, sizeof(VertexData));

    m_earthProgram->enableAttributeArray(1);
    m_earthProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(VertexData, normal), 3, sizeof(VertexData));

    m_earthProgram->enableAttributeArray(2);
    m_earthProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(VertexData, texCoord), 2, sizeof(VertexData));

    m_earthVao.release();
}

void EarthWidget::createMarkerGeometry()
{
    m_markerVertices.clear();
    m_markerIndices.clear();

    // 创建一个小金字塔作为标记
    float size = 0.05f;
    float height = 0.15f;

    // 顶点数据
    QVector<VertexData> vertices = {
                                    // 底面正方形
                                    {QVector3D(-size, 0, -size), QVector3D(0, -1, 0), QVector2D(0, 0)},
                                    {QVector3D(size, 0, -size), QVector3D(0, -1, 0), QVector2D(1, 0)},
                                    {QVector3D(size, 0, size), QVector3D(0, -1, 0), QVector2D(1, 1)},
                                    {QVector3D(-size, 0, size), QVector3D(0, -1, 0), QVector2D(0, 1)},

                                    // 顶点
                                    {QVector3D(0, height, 0), QVector3D(0, 1, 0), QVector2D(0.5, 0.5)},
                                    };

    QVector<GLuint> indices = {
        // 底面
        0, 1, 2, 0, 2, 3,
        // 侧面
        0, 1, 4,
        1, 2, 4,
        2, 3, 4,
        3, 0, 4
    };

    m_markerVertices = vertices;
    m_markerIndices = indices;

    // 设置标记VAO和VBO
    m_markerVao.create();
    m_markerVao.bind();

    m_markerVbo = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    m_markerVbo.create();
    m_markerVbo.bind();
    m_markerVbo.allocate(m_markerVertices.constData(), m_markerVertices.size() * sizeof(VertexData));

    m_markerIbo = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
    m_markerIbo.create();
    m_markerIbo.bind();
    m_markerIbo.allocate(m_markerIndices.constData(), m_markerIndices.size() * sizeof(GLuint));

    m_markerProgram->bind();

    m_markerProgram->enableAttributeArray(0);
    m_markerProgram->setAttributeBuffer(0, GL_FLOAT, offsetof(VertexData, position), 3, sizeof(VertexData));

    m_markerProgram->enableAttributeArray(1);
    m_markerProgram->setAttributeBuffer(1, GL_FLOAT, offsetof(VertexData, normal), 3, sizeof(VertexData));

    m_markerProgram->enableAttributeArray(2);
    m_markerProgram->setAttributeBuffer(2, GL_FLOAT, offsetof(VertexData, texCoord), 2, sizeof(VertexData));

    m_markerVao.release();
}

bool EarthWidget::loadEarthTexture(const QString& imagePath)
{
    if (!QFile::exists(imagePath)) {
        qWarning() << "Texture file not found:" << imagePath;
        return false;
    }

    QImage earthImage;
    if (!earthImage.load(imagePath)) {
        qWarning() << "Failed to load texture image:" << imagePath;
        return false;
    }

    // 转换为RGBA格式并镜像
    earthImage = earthImage.convertToFormat(QImage::Format_RGBA8888).mirrored();

    makeCurrent();

    if (m_textureLoaded && m_earthTexture != 0) {
        glDeleteTextures(1, &m_earthTexture);
        m_earthTexture = 0;
    }

    m_earthTexture = loadTexture(earthImage);
    m_textureLoaded = (m_earthTexture != 0);

    doneCurrent();

    if (m_textureLoaded) {
        update();
        qDebug() << "Earth texture loaded successfully:" << imagePath;
    } else {
        qWarning() << "Failed to load earth texture:" << imagePath;
    }

    return m_textureLoaded;
}

void EarthWidget::downloadNASATexture(const QString& urlString)
{
    // 检查是否有缓存
    QString filename = QUrl(urlString).fileName();
    QString cachedPath = getCachedTexturePath(filename);

    if (QFile::exists(cachedPath)) {
        qDebug() << "使用缓存的纹理:" << cachedPath;
        if (loadEarthTexture(cachedPath)) {
            emit textureLoaded(true);
            return;
        }
    }

    // 没有缓存，从网络下载
    QUrl url(urlString);
    QNetworkRequest request(url);
    request.setRawHeader("User-Agent", "EarthViewer/1.0");

    qDebug() << "下载NASA纹理:" << urlString;
    m_networkManager->get(request);
}

void EarthWidget::downloadDefaultNASATexture(TextureType type)
{
    QString url;

    switch (type) {
    case BlueMarbleHD:
        url = "https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73963/world.topo.200407.3x5400x2700.jpg";
        break;
    case BlueMarble4K:
        url = "https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73963/world.topo.200407.3x10800x5400.jpg";
        break;
    case NightLights:
        url = "https://eoimages.gsfc.nasa.gov/images/imagerecords/144000/144898/BlackMarble_2016_01deg.jpg";
        break;
    case Topography:
        url = "https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73934/topo_july_4k.jpg";
        break;
    case CloudCover:
        url = "https://eoimages.gsfc.nasa.gov/images/imagerecords/57000/57752/cloud_combined_2048.jpg";
        break;
    }

    if (!url.isEmpty()) {
        downloadNASATexture(url);
    }
}

void EarthWidget::onTextureDownloaded(QNetworkReply* reply)
{
    if (reply->error() == QNetworkReply::NoError) {
        QByteArray imageData = reply->readAll();
        QImage earthImage;

        if (earthImage.loadFromData(imageData)) {
            qDebug() << "NASA纹理下载成功! 尺寸:"
                     << earthImage.width() << "x" << earthImage.height();

            // 保存到缓存
            QString filename = QUrl(reply->url().toString()).fileName();
            saveDownloadedTexture(earthImage, filename);

            // 转换为RGBA格式
            earthImage = earthImage.convertToFormat(QImage::Format_RGBA8888).mirrored();

            makeCurrent();

            if (m_textureLoaded && m_earthTexture != 0) {
                glDeleteTextures(1, &m_earthTexture);
                m_earthTexture = 0;
            }

            m_earthTexture = loadTexture(earthImage);
            m_textureLoaded = (m_earthTexture != 0);

            doneCurrent();

            if (m_textureLoaded) {
                update();
                emit textureLoaded(true);
            } else {
                emit textureLoaded(false);
            }
        } else {
            emit textureLoaded(false);
        }
    } else {
        emit textureLoaded(false);
    }

    reply->deleteLater();
}

void EarthWidget::mousePressEvent(QMouseEvent *event)
{
    m_lastMousePos = event->pos();

    if (event->button() == Qt::LeftButton) {
        // 检查是否点击了地球表面
        QVector3D worldPos = screenToWorldCoordinates(event->x(), event->y());

        if (!worldPos.isNull()) {
            // 点击了地球表面，添加标记
            QVector3D geoCoord = cartesianToGeographic(worldPos);
            float latitude = geoCoord.x();
            float longitude = geoCoord.y();

            qDebug() << "添加标记 - 纬度:" << latitude << "经度:" << longitude;

            // 如果有加载的模型，放置模型；否则添加标记
            if (!m_loadedModels.isEmpty()) {
                QString firstModel = m_loadedModels.keys().first();
                addModelAtLocation(latitude, longitude, firstModel, QVector3D(0.01f, 0.01f, 0.01f));
            } else {
                addMarker(latitude, longitude);
                emit markerAdded(latitude, longitude);
            }
        } else {
            // 没有点击到地球表面，开始旋转
            m_isRotating = true;
        }
    } else if (event->button() == Qt::RightButton) {
        // 右键总是旋转
        m_isRotating = true;
    }

    update();
}

void EarthWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isRotating || (event->buttons() & Qt::RightButton)) {
        int dx = event->x() - m_lastMousePos.x();
        int dy = event->y() - m_lastMousePos.y();

        m_rotationY += dx * 0.5f;
        m_rotationX += dy * 0.5f;

        m_rotationX = qBound(-90.0f, m_rotationX, 90.0f);

        m_lastMousePos = event->pos();
        update();
    }
}

void EarthWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) {
        m_isRotating = false;
    }
}

void EarthWidget::wheelEvent(QWheelEvent *event)
{
    QPoint numDegrees = event->angleDelta() / 8;
    if (!numDegrees.isNull()) {
        float delta = numDegrees.y() * 0.01f;
        m_distance = qBound(2.0f, m_distance - delta, 20.0f);
        update();
    }
    event->accept();
}

QVector3D EarthWidget::screenToWorldCoordinates(int x, int y)
{
    // 将屏幕坐标转换为标准化设备坐标
    float ndcX = (2.0f * x) / width() - 1.0f;
    float ndcY = 1.0f - (2.0f * y) / height();

    // 创建近平面和远平面的点
    QVector4D rayStart(ndcX, ndcY, -1.0f, 1.0f);  // 近平面
    QVector4D rayEnd(ndcX, ndcY, 1.0f, 1.0f);     // 远平面

    // 转换到世界坐标
    QMatrix4x4 inverseMVP = (m_projection * m_view * m_model).inverted();
    QVector4D worldStart = inverseMVP * rayStart;
    QVector4D worldEnd = inverseMVP * rayEnd;

    // 齐次坐标除法
    worldStart /= worldStart.w();
    worldEnd /= worldEnd.w();

    // 创建射线
    QVector3D rayOrigin = worldStart.toVector3D();
    QVector3D rayEndPos = worldEnd.toVector3D();
    QVector3D rayDir = (rayEndPos - rayOrigin).normalized();

    // 射线与球体求交（使用正确的球体方程）
    QVector3D sphereCenter(0.0f, 0.0f, 0.0f);
    float sphereRadius = m_radius;

    // 球体方程: (P - C)² = R²
    // 射线方程: P = O + tD
    // 代入得: (O + tD - C)² = R²
    // 展开: (D·D)t² + 2D·(O-C)t + (O-C)² - R² = 0

    QVector3D oc = rayOrigin - sphereCenter;
    float a = QVector3D::dotProduct(rayDir, rayDir);
    float b = 2.0f * QVector3D::dotProduct(oc, rayDir);
    float c = QVector3D::dotProduct(oc, oc) - sphereRadius * sphereRadius;

    float discriminant = b * b - 4 * a * c;

    if (discriminant < 0) {
        return QVector3D(); // 没有交点
    }

    // 计算两个交点
    float sqrtDiscriminant = std::sqrt(discriminant);
    float t1 = (-b - sqrtDiscriminant) / (2.0f * a);
    float t2 = (-b + sqrtDiscriminant) / (2.0f * a);

    // 选择最近的且在相机前方的交点
    float t = -1.0f;
    if (t1 > 0 && t2 > 0) {
        t = std::min(t1, t2);
    } else if (t1 > 0) {
        t = t1;
    } else if (t2 > 0) {
        t = t2;
    } else {
        return QVector3D(); // 交点都在相机后方
    }

    // 验证交点是否在合理范围内
    if (t < 0 || t > 100.0f) {
        return QVector3D();
    }

    QVector3D intersection = rayOrigin + rayDir * t;

    // 验证交点是否在球体表面（考虑浮点误差）
    float distanceFromCenter = (intersection - sphereCenter).length();
    if (std::abs(distanceFromCenter - sphereRadius) > 0.01f) {
        return QVector3D();
    }

    return intersection;
}

QVector3D EarthWidget::cartesianToGeographic(const QVector3D& point)
{
    float x = point.x();
    float y = point.y();
    float z = point.z();

    float latitude = std::asin(y / m_radius) * 180.0f / M_PI;
    float longitude = std::atan2(z, x) * 180.0f / M_PI;

    return QVector3D(latitude, longitude, 0.0f);
}

void EarthWidget::addMarker(float latitude, float longitude, const QVector3D& color)
{
    // 将地理坐标转换为笛卡尔坐标
    float latRad = latitude * M_PI / 180.0f;
    float lonRad = longitude * M_PI / 180.0f;

    float x = m_radius * std::cos(latRad) * std::cos(lonRad);
    float y = m_radius * std::sin(latRad);
    float z = m_radius * std::cos(latRad) * std::sin(lonRad);

    Marker marker;
    marker.position = QVector3D(x, y, z);
    marker.color = color;

    // 创建变换矩阵，使标记垂直于球面
    marker.modelMatrix.setToIdentity();
    marker.modelMatrix.translate(marker.position);

    // 计算旋转使标记指向球心
    QVector3D up(0.0f, 1.0f, 0.0f);
    QVector3D normal = marker.position.normalized();
    QVector3D right = QVector3D::crossProduct(up, normal).normalized();
    QVector3D localUp = QVector3D::crossProduct(normal, right).normalized();

    QMatrix4x4 rotation;
    rotation.setColumn(0, QVector4D(right, 0.0f));
    rotation.setColumn(1, QVector4D(localUp, 0.0f));
    rotation.setColumn(2, QVector4D(normal, 0.0f));

    marker.modelMatrix = marker.modelMatrix * rotation;

    m_markers.append(marker);
}

void EarthWidget::clearMarkers()
{
    m_markers.clear();
    update();
}
